#ifndef REMOTE_CLIENT_TUNNEL_SERVICES_H_
#define REMOTE_CLIENT_TUNNEL_SERVICES_H_

#include "remote/client/clientcontrolsession.h"
#include "remote/client/task.h"
#include "vzconn/conn/vzserver.h"
#include "remote/client/tunnelsession.h"
#include <set>

namespace remote {

class ReqTask : public boost::noncopyable,
  public boost::enable_shared_from_this < ReqTask > {
 public:
  typedef boost::shared_ptr<ReqTask> Ptr;

  boost::signals2::signal<void(
    ReqTask::Ptr req_task, uint32 code)> SignalConnectResult;

  ReqTask(boost::asio::io_service &io_service,
          TunnelSettings &tunnel_settings,
          vzconn::VzConnect::Ptr client_connect);
  virtual ~ReqTask();

  bool Start();
  void Stop();
 private:
  void OnServerConnectSucceed(vzconn::VzConnect::Ptr connect,
                              const boost::system::error_code& err);
  void OnServerConnectError(vzconn::VzConnect::Ptr connect,
                            const boost::system::error_code& err);
  void OnServerConnectWrite(vzconn::VzConnect::Ptr connect);
  void OnServerConnectRead(vzconn::VzConnect::Ptr connect,
                           const char* buffer, int size, int flag);
 private:
  boost::asio::io_service &io_service_;
  TunnelSettings &tunnel_settings_;
  vzconn::VzConnect::Ptr client_connect_;
  vzconn::VzConnect::Ptr server_connect_;
};

class TunnelServices : public boost::noncopyable,
  public boost::enable_shared_from_this < TunnelServices > {
 public:
  typedef boost::shared_ptr<TunnelServices> Ptr;
  TunnelServices(boost::asio::io_service &io_service,
                 TunnelSettings &tunnel_settings);
  virtual ~TunnelServices();
  bool StartTunnelServer();
  void Stop();
 private:
  void OnThreadRunning();
  void OnNewTunnelConnect(vzconn::VzServer::Ptr tcp_server,
                          vzconn::VzConnect::Ptr tcp_connect);
  void OnTunnelServerError(vzconn::VzServer::Ptr tcp_server,
                           const boost::system::error_code& err);
 private:
  boost::asio::io_service &io_service_;
  TunnelSettings tunnel_settings_;
  boost::scoped_ptr<boost::thread> tunnel_thread_;
  boost::scoped_ptr<boost::asio::io_service> thread_io_service_;
  vzconn::VzServer::Ptr tunnel_server_;
};

}
#endif  // REMOTE_CLIENT_TUNNEL_SERVICES_H_
